﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Pavilion.DesignerTool.ViewTools.ConnectableListBox;
using Pavilion.DesignerTool.NodeDesignerTool.Scripting;
using System.Windows;
using System.Xml.Linq;
using System.IO;

namespace Pavilion.DesignerTool
{
    public class NodeScriptViewModel : INotifyPropertyChanged
    {
        static private NodeCopyPasteMananger copyPasteManager = new NodeCopyPasteMananger();

        public event PropertyChangedEventHandler PropertyChanged;
        public event Action<object> SelectedItemChanged;

        public string NodeScriptName { get { return nodeScriptWrapper.ResourceData.ResourceName + "." + nodeScriptWrapper.Name; } }
        public bool CanStepOut { get { return (CurrentContainerNode != null) && (CurrentContainerNode.ParentContainer != null); } }

        public object SelectedItem { get { return selectedItem; } set { selectedItem = value; OnSelectedItemChanged(selectedItem); } }
        public NodeScriptWrapper NodeScriptWrapper { get { return nodeScriptWrapper; } set { SetNodeScriptWrapper(value); } }
        public ContainerNode CurrentContainerNode { get { return (ConnectableItemContainer != null) ? ConnectableItemContainer.ContainerNode : null; } }
        public ContainerNodeWrapper ConnectableItemContainer { get { return connectableItemContainer; } set { connectableItemContainer = value; OnPropertyChanged("ConnectableItemContainer"); OnPropertyChanged("CurrentContainerNode"); } }

        private ContainerNodeWrapper connectableItemContainer;
        private NodeScriptWrapper nodeScriptWrapper;
        private object selectedItem;

        internal NodeBaseWrapper AddNewAnimationNode()
        {
            return AddNode(new AnimationNode(this.CurrentContainerNode.GetUniqueName("AnimationNode")));
        }

        internal NodeBaseWrapper AddNewContainerNode()
        {
            return AddNode(new ContainerNode(this.CurrentContainerNode.GetUniqueName("ContainerNode")));
        }

        public NodeBaseWrapper AddNewLoadNode()
        {
            return AddNode(new LoadNode(this.CurrentContainerNode.GetUniqueName("LoadNode")));
        }

        internal NodeBaseWrapper AddNewDefaultNode()
        {
            return AddNode(new DefaultNode(this.CurrentContainerNode.GetUniqueName("DefaultNode")));
        }

        internal NodeBaseWrapper AddNode(NodeBase node)
        {
            return this.ConnectableItemContainer.AddNode(node);
        }

        internal void AddNode(NodeBaseWrapper nodeWrapper)
        {
            this.ConnectableItemContainer.AddNewNodeWrapper(nodeWrapper);
        }

        internal void RemoveNodes(IEnumerable<NodeBaseWrapper> selectedNodes)
        {
            foreach (NodeBaseWrapper node in selectedNodes)
                this.ConnectableItemContainer.RemoveNode(node);
        }

        internal void AddLink(NodeBaseWrapper startNode, NodeBaseWrapper endNode)
        {
            ConnectableItemContainer.AddLink(startNode, endNode);
        }

        internal void AddLink(NodeBaseWrapper startNode, NodeBaseWrapper endNode, IEnumerable<ILock> lockCollection, OpenCriteria openCriteria)
        {
            ConnectableItemContainer.AddLink(startNode, endNode, lockCollection, openCriteria);
        }

        internal void RemoveLink(LinkWrapper linkWrapper)
        {
            LinkTransfer.Remove(linkWrapper);
            linkWrapper.Link.Dispose();
        }

        internal void StepIntoNode(IConnectableItem connectableItem)
        {
            if (connectableItem is ContainerNodeWrapper)
                this.ConnectableItemContainer = connectableItem as ContainerNodeWrapper;
        }

        internal void StepOutOfNode()
        {
            this.ConnectableItemContainer = ConnectableItemContainer.ParentContainerNodeWrapper;
        }

        internal void CopySelectedItems(object[] array)
        {
            copyPasteManager.CopySelectedItems(array);
        }

        internal void Paste()
        {
            copyPasteManager.Paste(this);
        }

        private void SetNodeScriptWrapper(NodeScriptWrapper value)
        {
            if (nodeScriptWrapper == value)
                return;

            this.nodeScriptWrapper = value;

            if (nodeScriptWrapper == null)
                ConnectableItemContainer = null;
            else
                ConnectableItemContainer = value.RootContainerNodeWrapper;
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnSelectedItemChanged(object selectedItem)
        {
            if (SelectedItemChanged != null)
                SelectedItemChanged(selectedItem);
        }
    }
}
